import Cesium, { Cartesian3, Cartographic } from '../Ces/Cesium'
import We from '../Core/We'
import EditablePoint from './EditablePoint'

class PositionHandler {
  _debug
  _toolTip
  _mouseMoveHandler
  _leftClickHandler
  _leftDownkHandler
  _leftUpHandler

  WE: We
  heightReference
  _editablePoint
  _query
  _showPoint: boolean = true
  _showToolTip: boolean = true
  _isEditing: boolean = false
  _position: Cartesian3 = new Cesium.Cartesian3()
  _scratchCartographic: Cartographic = new Cesium.Cartographic()
  _minPickHeight: number = -10.0

  constructor(WE) {
    this.WE = WE
    this.heightReference = WE.heightReference
  }
  get toolTip() {
    return this._toolTip
  }
  get showPoint() {
    return this._showPoint
  }
  set showPoint(value) {
    this._showPoint = value
  }
  get showToolTip() {
    return this._showToolTip
  }
  set showToolTip(value) {
    this._showToolTip = value
  }
  get query() {
    return this._query
  }
  set query(value) {
    this._query = this._query && this._query.destroy()
    this._query = value
  }
  get isEditing() {
    return this._isEditing && !this.WE.viewer.scene.screenSpaceCameraController.enableInputs
  }
  set isEditing(value) {
    this._isEditing = value
    this.WE.viewer.scene.screenSpaceCameraController.enableInputs = !this._isEditing
    if (this._editablePoint) {
      this._editablePoint.allowPick = !this._isEditing
    }
  }


  start() {
    this.createMouseMoveHandler(this.WE.viewer.scene)
    this.createLeftClickHandler(this.WE.viewer.scene)
    this.createLeftDownHandler(this.WE.viewer.scene)
    this.createLeftUpHandler(this.WE.viewer.scene)
  }

  validPosition(position) {
    if (this._query && this._query.validPosition) {
      return this._query.validPosition(position)
    }

    if (position) {
      const cartographic = Cesium.Cartographic.fromCartesian(position, undefined, this._scratchCartographic)

      return cartographic.height > this._minPickHeight
    }

    return false
  }

  pickPosition(scene, screenPosition) {
    if (this._query && this._query.pickPosition) {
      return this._query.pickPosition(scene, screenPosition, this._position)
    }

    let position

    const pickedFeature = scene.pick(screenPosition)

    if (Cesium.defined(pickedFeature) &&
      (!this._editablePoint || pickedFeature.id !== this._editablePoint)
    ) {
      position = scene.pickPosition(screenPosition, this._position)
    } else if (this.heightReference === Cesium.HeightReference.NONE) {
      position = scene.camera.pickEllipsoid(
        screenPosition,
        scene.globe.ellipsoid,
        this._position,
      )
    } else {
      const ray = scene.camera.getPickRay(screenPosition)

      position = scene.globe.pick(ray, scene, this._position)
    }

    return position
  }

  onPostionChanged(
    entity,
    propertyName,
    cartesian,
    tooltip,
  ) {
    const cartographic = Cesium.Cartographic.fromCartesian(cartesian)
    const longitude = Cesium.Math.toDegrees(cartographic.longitude)
    const latitude = Cesium.Math.toDegrees(cartographic.latitude)
    const height = (cartographic.height > -1e-6 && cartographic.height < 1e-6) ? 0.0 : cartographic.height

    let content = `经度${longitude.toFixed(4).padStart(8)}<br/>纬度 ${latitude.toFixed(4).padStart(8)}`

    if (height !== 0.0) {
      content += `<br/>高度${height.toFixed(2).padStart(8)}`
    }

    if (this._debug) {
      content += `<br/>debug${this._debug}`
    }

    this._position.x = cartesian.x
    this._position.y = cartesian.y
    this._position.z = cartesian.z

    if (tooltip && tooltip === this._toolTip) {
      tooltip.visible = true
      tooltip.position = cartesian
      tooltip.content = content
    }
  }

  showPosition(_cartesian) {
    this._position = _cartesian
    if (!this._editablePoint) {
      const that = this

      this._editablePoint = new EditablePoint()
      this._editablePoint.position = this._position
      this._editablePoint.isPrivate = true
      this._editablePoint.onPostionChanged = (
        entity,
        propertyName,
        newValue,
        oldValue,
      ) => {
        that.onPostionChanged(
          entity,
          propertyName,
          newValue,
          oldValue,
        )
      }
    }

    if (this._showToolTip) {
      if (!this._toolTip) {
        this._toolTip = this.WE.earthPinCollection.getOrCreateToolTip('PositionHandler', {
          align: 'right',
        })
      }
    }
    this.updatePosition(this._position)
  }

  updatePosition(position) {
    if (Cesium.defined(this._editablePoint)) {
      this._editablePoint.updatePosition(position, this._toolTip)
    }
  }

  createMouseMoveHandler(scene) {
    const that = this
    const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)

    handler.setInputAction((movement) => {
      if (that.isEditing) {
        const position = that.pickPosition(scene, movement.endPosition)

        if (that.validPosition(position)) {
          that.updatePosition(position)
        }
      } else {
        const pickedFeature = scene.pick(movement.endPosition)

        if (Cesium.defined(pickedFeature)
          && Cesium.defined(that._editablePoint)
          && pickedFeature.id === that._editablePoint) {
          that._editablePoint.onHighlight()
        } else if (that._editablePoint) {
          that._editablePoint.offHighlight()
        }
      }
    }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
    this._mouseMoveHandler = handler
  }

  createLeftClickHandler(scene) {
    const that = this
    const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)

    handler.setInputAction((movement) => {
      const position = that.pickPosition(scene, movement.position)

      if (that.validPosition(position)) {
        that.showPosition(position)
      }
    }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    this._leftClickHandler = handler
  }

  createLeftDownHandler(scene) {
    const that = this
    const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)

    handler.setInputAction((movement) => {
      const pickedFeature = scene.pick(movement.position)

      if (Cesium.defined(pickedFeature)
        && Cesium.defined(that._editablePoint)
        && pickedFeature.id === that._editablePoint) {
        that._editablePoint.onHighlight()
        that.isEditing = true
      }
    }, Cesium.ScreenSpaceEventType.LEFT_DOWN)
    this._leftDownkHandler = handler
  }

  createLeftUpHandler(scene) {
    const that = this
    const handler = new Cesium.ScreenSpaceEventHandler(scene.canvas)

    handler.setInputAction(() => {
      that.isEditing = false
      if (that._editablePoint) {
        that._editablePoint.offHighlight()
      }
    }, Cesium.ScreenSpaceEventType.LEFT_UP)
    this._leftUpHandler = handler
  }

  update(frameState) {
    if (this._showPoint && this._editablePoint) {
      this._editablePoint.update(frameState)
    }
    if (this._query) {
      this._query.update(frameState)
    }
  }

  isDestroyed() {
    return false
  }

  destroy() {
    if (this._toolTip) {
      this.WE.earthPinCollection.remove(this._toolTip)
      this._toolTip = undefined
    }
    this._leftClickHandler = this._leftClickHandler && this._leftClickHandler.destroy()
    this._leftUpHandler = this._leftUpHandler && this._leftUpHandler.destroy()
    this._leftDownkHandler = this._leftDownkHandler && this._leftDownkHandler.destroy()
    this._mouseMoveHandler = this._mouseMoveHandler && this._mouseMoveHandler.destroy()
    this._editablePoint = this._editablePoint && this._editablePoint.destroy()
    this._query = this._query && this._query.destroy()

    return Cesium.destroyObject(this)
  }
}




export default PositionHandler
